use std::string::ToString;
use openssl::base64::encode_block;
use openssl::hash::MessageDigest;
use openssl::sign::Signer;
use serde::{Deserialize, Serialize};
use tracing::{debug, info};
use crate::{get_random_string, AppResult};
use crate::context::certificate::get_certificate_context;

#[derive(Debug,Serialize,Deserialize)]
pub struct Product{
    code:String,
    #[serde(rename = "fallbackDate")]
    fallback_date:String,
    #[serde(rename = "paidUpTo")]
    paid_up_to:String,
}
#[derive(Debug,Serialize,Deserialize)]
pub struct LicensePart {
    #[serde(rename = "licenseId")]
    license_id: String,
    #[serde(rename = "licenseeName")]
    license_name: String,
    #[serde(rename = "assigneeName")]
    assignee_name: String,
    products: Vec<Product>,
    /**
    * 元数据信息，默认值说明：
    * - 01: 版本标识
    * - 20230914: 日期标识
    * - PSAX000005: 产品类型和序列号
    */
    metadata: &'static str,
}
const LICENSE_PART_METADATA: &str = "0120230914PSAX000005";
pub async  fn generate_license(license_name: String, assignee_name: String, expiry_date: String, product_code_set: Vec<String>) -> AppResult<String> {
    info!("开始生成License文件,许可证名称: {}, 被授权人: {}, 过期日期: {}, 产品数量: {}", license_name, assignee_name, expiry_date, product_code_set.len());
    let license_id = get_random_string::<20>()?;
    debug!("生成随机数: {:?}", license_id);
   let products: Vec<Product> = product_code_set.iter()
        .map(|product_code| {
            let product = Product {
                code: product_code.to_string(),
                fallback_date: expiry_date.clone(),
                paid_up_to: expiry_date.clone(),
            };
            return product;
        }).collect();
    let license_part = LicensePart {
        license_id,
        license_name,
        assignee_name,
        products,
        metadata: LICENSE_PART_METADATA,
    };
    let license_part_json = serde_json::to_string(&license_part)?;
    let license_part_base64 = encode_block(&license_part_json.as_bytes());
    debug!("许可证JSON内容长度: {} 字符", license_part_json.len());
    let cert_context = get_certificate_context().await;
    let private_key = cert_context.cache().get_private_key();
    let code_cet = cert_context.cache().get_code_cet();
    let mut signer = Signer::new(MessageDigest::sha1(), &private_key)?;
    signer.update(license_part_json.as_bytes())?;
    let sign_data = encode_block(&signer.sign_to_vec()?);
    let cert_base64= encode_block(&code_cet.to_der()?);
    let activation_code = format!("{}-{}-{}-{}",license_part.license_id, license_part_base64, sign_data, cert_base64);
    info!("许可证生成成功 - 激活码长度: {} 字符", activation_code.len());
    Ok(activation_code)
}

#[cfg(test)]
mod tests {
    use super::*;
    #[tokio::test]
    async fn test_generate_license()->AppResult< ()> {
        let license_part = LicensePart {
            license_id: "1".to_string(),
            license_name: "1".to_string(),
            assignee_name: "1".to_string(),
            products: vec![Product {code: "1".to_string(), fallback_date: "1".to_string(), paid_up_to: "1".to_string()}],
            metadata: LICENSE_PART_METADATA,
        };
        let license_part_json = serde_json::to_string(&license_part)?;
        let cert_context = get_certificate_context().await;
        let private_key = cert_context.cache().get_private_key();
        let code_cet = cert_context.cache().get_code_cet();
        let mut signer = Signer::new(MessageDigest::sha1(), &private_key)?;
        signer.update(license_part_json.as_bytes())?;
        let sign_data = encode_block(&signer.sign_to_vec()?);
        println!("{}", license_part_json);
        println!("{}", sign_data);
        Ok(())
    }
}